#include "../source/server.hpp"

#include <iostream>
#include <time.h>
// #include <stdlib.h> // atoi 函数需要的头文件

using namespace std;

void HandleClose(Channel *channel)
{
    // std::cout << "close: " << channel->Fd() << std::endl;
    DBG_LOG("close: %d", channel->Fd());
    channel->Remove(); // 移除清空
    delete channel;
}

void HandleRead(Channel *channel)
{
    int fd = channel->Fd();
    char buffer[1024] = {0};
    int ret = recv(fd, buffer, 1023, 0);
    if (ret <= 0)
    {
        return HandleClose(channel); // 关闭释放
    }
    DBG_LOG("%s", buffer);
    // std::cout << buffer << std::endl;
    channel->EnableWrite(); // 启动可写事件
}

void HandleWrite(Channel *channel)
{
    int fd = channel->Fd();
    const char *str = "nihao";
    int ret = send(fd, str, strlen(str), 0);
    if (ret < 0)
    {
        return HandleClose(channel);
    }
    channel->DisableWrite(); // 关闭写监控
}

void HandleError(Channel *channel)
{
    return HandleClose(channel);
}

void HandleEvent(EventLoop *loop, Channel *channel, uint64_t timerid)
{
    // std::cout << "有了一个事件!!!" << std::endl;
    loop->TimerRefresh(timerid);
    static int count = 0;
    DBG_LOG("刷新了%d次!!!", ++count);
}

void Accept(EventLoop *loop, Channel *server_channel, int cnt)
{
    int server_fd = server_channel->Fd();
    int newfd = accept(server_fd, NULL, NULL);
    if (newfd < 0)
        return;

    uint64_t timerid = rand() % 10000;
    Channel *new_channel = new Channel(loop, newfd);
    new_channel->SetReadCallback(std::bind(HandleRead, new_channel)); // 为新的通信套接字设置可读事件的回调函数
    new_channel->SetWriteCallback(std::bind(HandleWrite, new_channel));
    new_channel->SetCloseCallback(std::bind(HandleClose, new_channel));
    new_channel->SetErrorCallback(std::bind(HandleError, new_channel));
    new_channel->SetEventCallback(std::bind(HandleEvent, loop, new_channel, timerid));
    // new_channel->EnableRead();

    // 非活跃连接的超时释放操作，cnt秒后关闭连接
    // 注意：定时销毁任务，必须在启动读事件之前，因为有可能启动了事件监控后，立即就有了事件，但是这时候还没有任务
    // 当client向server发送数据的时候，就会执行HandleEvent函数的回调 ---> 就会刷新一次即 _tick 秒针向后走一次
    loop->TimerAdd(timerid, cnt, std::bind(HandleClose, new_channel));

    new_channel->EnableRead();
}

// ./server cnt
int main(int argc, char *argv[])
{
    // 手动传入体格定时事件触发的秒数 cnt
    if (argc != 2)
    {
        ERR_LOG("argc != %d", argc);
        return 0;
    }
    uint32_t cnt = atoi(argv[1]);
    cout << "cnt = " << cnt << endl;

    srand(time(nullptr));
    // Poller poller; // 管理多个 Channel 的类
    EventLoop loop;
    Socket server;
    server.CreateServer(8500);
    // 为监听套接字，创建一个Channel进行事件的管理，以及事件的处理
    Channel channel(&loop, server.Fd());
    channel.SetReadCallback(std::bind(Accept, &loop, &channel, cnt)); // 回调中，获取新连接，并未新连接创建Channel，并添加监控
    channel.EnableRead();
    while (true)
    {
        loop.start();

        sleep(1);
    }
    server.Close();

    return 0;
}
